using UnityEditor;
using UnityEngine;

namespace Learning
{
    [RequireComponent(typeof(Animator))]
    public class MaterialFunc : MonoBehaviour
    {
        private static readonly int ShowFlagID = Shader.PropertyToID("_ShowFlag");
        private static readonly int TexIndexID = Shader.PropertyToID("_TexIndex");
        private static readonly int CampColorID = Shader.PropertyToID("_CampColor");
        
        private Animator _animator;
        private Material _material;
        
        // 缓存所有旗子渲染之后的效果贴图，之所以使用 Texture2DArray 传入全部旗帜到材质中，是后期配合GPUInstancing时，一个DC可以绘制所有不同的旗帜图形
        private Texture2DArray _texture2DArray;
        
        void Start()
        {
            _animator = GetComponent<Animator>();
            _animator.Play("stand");

            _material = GetComponentInChildren<SkinnedMeshRenderer>().sharedMaterial;
            
            InitAllFlag();
        }

        // 先使用旗子生成的Shader对所有旗帜进行渲染后存储到Texture2DArray中
        private void InitAllFlag()
        {
            const int textureWidth = 128;
            const int textureHeight = 128;
            var colors = new Color[] { Color.gray, Color.green, Color.yellow, Color.white, Color.blue, Color.cyan };
            
            _texture2DArray = new Texture2DArray(textureWidth, textureHeight, 6, TextureFormat.RGBA32, false);
            var mixer = AssetDatabase.LoadAssetAtPath<Material>("Assets/Learning/MaterialFunc/Res/flag_mixer.mat");
            for (int i = 0; i < 6; i++)
            {
                var badge = AssetDatabase.LoadAssetAtPath<Texture2D>($"Assets/Learning/MaterialFunc/Res/badge{i + 1}.png");
                mixer.SetTexture("_BadgeTexture", badge);
                mixer.SetColor("_FlagColor", colors[i]);
                mixer.SetInt("_Count", 1);
                var texture = GraphicsBlit(mixer, textureWidth, textureHeight);
                _texture2DArray.SetPixels(texture.GetPixels(0), i);
            }
            _texture2DArray.Apply();
            
            _material.SetTexture("_TexArray", _texture2DArray);
        }
        
        public static Texture2D GraphicsBlit(Material mat, int width, int height) {
            var rt = RenderTexture.GetTemporary(width, height, 0);
            Graphics.Blit(null, rt, mat);
            var texture = new Texture2D(rt.width, rt.height, TextureFormat.RGBA32, false);
            RenderTexture.active = rt;
            texture.ReadPixels(new Rect(0, 0, width, height), 0, 0);
            texture.Apply();
            RenderTexture.ReleaseTemporary(rt);
            return texture;
        }

        public void ShowOrHideFlag()
        {
            if (_material.HasProperty(ShowFlagID))
            {
                var show = _material.GetFloat(ShowFlagID);
                _material.SetFloat(ShowFlagID, show == 0f ? 1f : 0f);
            }
        }

        public void ChangeSoliderColor()
        {
            if (_material.HasProperty(CampColorID))
            {
                _material.SetColor(CampColorID, Color.red);
            }
        }

        public void ChangeFlagTexture()
        {
            if (_material.HasProperty(TexIndexID))
            {
                var index = _material.GetFloat(TexIndexID);
                index++;
                index %= 6;
                _material.SetFloat(TexIndexID, index);
            }
        }
    }
}
